// LR(0) 解析html
// 遇到开始标签时创建元素并入栈，遇到结束标签时出栈
// 自封闭节点可视为入栈后立刻出栈
// 任何元素的父元素是它入栈前的栈顶
let stack = [{ type: 'document', children: [] }]
function emit(token) {
  if (token.type === 'text') return

  let top = stack[stack.length - 1]

  if (token.type === 'startTag') {
    let element = {
      type: 'element', // <tag>  背后表示的叫做 抽象概念 element node ...
      children: [],
      attributes: [],
    }
    element.tagName = token.tagName
    for (let p in token) {
      if (p !== 'type' && p !== 'tagName') {
        element.attributes.push({
          name: p,
          value: token[p],
        })
      }
    }
    top.children.push(element)
    element.parent = top

    if (!token.isSelfClosing) stack.push(element)

    currentTextNode = null
  } else if (token.type === 'endTag') {
    if (top.tagName !== token.tagName) {
      throw new Error("tag start end doesn't match")
    } else {
      stack.pop()
    }
    currentTextNode = null
  }
}
{
  /* < html style="width: 100px;" >
  <body>
    <div>
      <p>
        <span></span>
        <span />
      </p>
    </div>
  </body>
</html> */
}
// 1
emit({
  type: 'startTag',
  tagName: 'html',
  style: {
    width: '100px',
  },
})
//2
emit({
  type: 'startTag',
  tagName: 'body',
})
//3
emit({
  type: 'startTag',
  tagName: 'div',
})
//4
emit({
  type: 'startTag',
  tagName: 'p',
})
//5
emit({
  type: 'startTag',
  tagName: 'span',
})
//6
emit({
  type: 'endTag',
  tagName: 'span',
})
//7
emit({
  type: 'startTag',
  tagName: 'span',
  isSelfClosing: 'true',
})
//8
emit({
  type: 'endTag',
  tagName: 'p',
})
//9
emit({
  type: 'endTag',
  tagName: 'div',
})
//10
emit({
  type: 'endTag',
  tagName: 'body',
})
// 11
emit({
  type: 'endTag',
  tagName: 'html',
})

console.log(stack[0])
